package main

import (
	"embed"
	"flag"
	"fmt"
	"log"
	"net/http"
	"os"
	"runtime"
	"time"

	"github.com/robfig/cron/v3"

	"skedule-backend/auth"
	"skedule-backend/config"
	"skedule-backend/database"
	"skedule-backend/handlers"
	"skedule-backend/routes"
	"skedule-backend/scheduler"
	"skedule-backend/storage"
	"skedule-backend/middleware"
	"skedule-backend/utils"
	"skedule-backend/service"
)

// 版本信息 - 编译时通过 -ldflags 注入
var (
	Version   = "dev"      // 从 package.json 读取
	BuildDate = "unknown"  // 编译时当前时间
	GitCommit = "unknown"  // git commit hash
)

// 嵌入前端静态文件
//go:embed dist/frontend/dist/*
var embeddedDist embed.FS

// 命令行参数变量
var (
	version      *bool
	versionShort *bool
	mode         *string
	username     *string
	password     *string
	jwtSecret    *string
	port         *string
	configOnly   *bool
	showConfig   *bool
	enableLogging *bool
	logLevel     *string
	debug        *bool
)

func main() {
	// 先尝试检测语言设置
	initializeLanguage()
	
	// 定义命令行参数
	defineFlags()
	
	// 解析命令行参数
	flag.Parse()

	// 显示版本信息
	if *version || *versionShort {
		// 版本信息显示需要重新加载配置以获取准确的语言设置
		cfg, err := config.GetConfig()
		if err != nil {
			// 如果配置文件读取失败，保持当前语言设置
		} else {
			utils.InitI18n(cfg)
		}
		printVersionInfo()
		return
	}

	// 先加载配置以获取数据库路径和语言设置
	cfg, err := config.GetConfig()
	if err != nil {
		log.Fatalf("Failed to load configuration: %v", err)
	}

	// 初始化国际化
	utils.InitI18n(cfg)

	// 使用配置中的数据库路径初始化数据库
	if err := database.InitDB(cfg.Database.Path); err != nil {
		log.Fatalf(utils.T("server.database.failed"), err)
	}
	fmt.Println(utils.T("server.database.success"))

	// 如果只是显示配置
	if *showConfig {
		fmt.Printf(utils.T("config.current") + "\n")
		fmt.Printf(utils.T("config.port") + "\n", cfg.Server.Port)
		fmt.Printf(utils.T("config.ip") + "\n", cfg.Server.IP)
		fmt.Printf(utils.T("config.database") + "\n", cfg.Database.Path)
		fmt.Printf(utils.T("config.username") + "\n", cfg.Auth.Username)
		fmt.Printf(utils.T("config.password.encrypted") + "\n", cfg.Auth.Password)
		fmt.Printf(utils.T("config.salt") + "\n", cfg.Auth.Salt)
		return
	}

	// 根据模式执行不同操作
	switch *mode {
	case "password":
		// 修改密码模式
		salt := cfg.Auth.Salt
		encryptedPassword := auth.EncryptPassword(*password, salt)
		if err := auth.UpdatePassword(*username, encryptedPassword); err != nil {
			log.Fatalf(utils.T("password.change.failed"), err)
		}
		fmt.Printf(utils.T("password.change.success") + "\n")
		fmt.Printf(utils.T("password.new.username") + "\n", *username)
		fmt.Printf(utils.T("password.new.password") + "\n", *password)
		fmt.Printf(utils.T("password.encrypted") + "\n", encryptedPassword)
		fmt.Printf(utils.T("password.salt") + "\n", salt)
		return
		
	case "server":
		// 服务器模式（传递已加载的配置）
		startServer(cfg, username, password, jwtSecret, port, configOnly, enableLogging, debug, logLevel)
		
	default:
		log.Fatalf(utils.T("error.mode.invalid"), *mode)
	}
}

// initializeLanguage 初始化语言设置
func initializeLanguage() {
	// 尝试从配置文件获取语言设置，如果失败则使用默认语言
	cfg, err := config.GetConfig()
	if err != nil {
		// 如果配置文件不存在或读取失败，检查系统语言
		if isChineseLocale() {
			utils.SetLanguage("zh")
		} else {
			utils.SetLanguage("en")
		}
	} else {
		utils.InitI18n(cfg)
	}
}

// isChineseLocale 检查是否为中文环境
func isChineseLocale() bool {
	lang := os.Getenv("LANG")
	return len(lang) >= 2 && (lang[:2] == "zh" || lang[:5] == "zh_CN" || lang[:5] == "zh_TW")
}

// defineFlags 定义命令行参数
func defineFlags() {
	version = flag.Bool("version", false, utils.T("flag.version"))
	versionShort = flag.Bool("v", false, utils.T("flag.version.short"))
	mode = flag.String("mode", "server", utils.T("flag.mode"))
	username = flag.String("username", "admin", utils.T("flag.username"))
	password = flag.String("password", "admin", utils.T("flag.password"))
	jwtSecret = flag.String("jwt-secret", "skedule-secret-key-2024", utils.T("flag.jwt.secret"))
	port = flag.String("port", "", utils.T("flag.port"))
	configOnly = flag.Bool("config-only", false, utils.T("flag.config.only"))
	showConfig = flag.Bool("show-config", false, utils.T("flag.show.config"))
	enableLogging = flag.Bool("enable-logging", true, utils.T("flag.enable.logging"))
	logLevel = flag.String("log-level", "info", utils.T("flag.log.level"))
	debug = flag.Bool("debug", false, utils.T("flag.debug"))
}

// startServer 启动服务器
func startServer(cfg *config.Config, username, password, jwtSecret, port *string, configOnly, enableLogging, debug *bool, logLevel *string) {
	log.Println(utils.T("server.starting"))
	
	// 设置调试模式
	config.SetDebugMode(*debug)
	if *debug {
		fmt.Println(utils.T("debug.enabled"))
	}
	
	// 如果只是更新配置
	if *configOnly {
		fmt.Printf(utils.T("config.updating") + "\n")
		fmt.Printf(utils.T("config.username") + "\n", *username)
		fmt.Printf(utils.T("password.new.password") + "\n", *password)
		if *port != "" {
			fmt.Printf(utils.T("config.port") + "\n", *port)
		}
		fmt.Printf(utils.T("config.updated") + "\n")
		return
	}

	// 如果指定了端口，更新配置
	if *port != "" {
		cfg.Server.Port = *port
	}

	// 初始化日志记录器
	log.Println(utils.T("server.logger.init"))
	if *enableLogging {
		if err := middleware.InitLoggerWithLevel(*logLevel); err != nil {
			log.Fatalf(utils.T("server.logger.failed"), err)
		}
		defer middleware.CloseLogger()
		fmt.Printf(utils.T("logging.enabled") + "\n", *logLevel)
		fmt.Printf(utils.T("logging.file") + "\n", time.Now().Format("2006-01-02"))
		fmt.Printf(utils.T("logging.detail") + "\n")
		switch *logLevel {
		case "debug":
			fmt.Printf(utils.T("logging.detail.debug") + "\n")
		case "info":
			fmt.Printf(utils.T("logging.detail.info") + "\n")
		case "warn", "error":
			fmt.Printf(utils.T("logging.detail.warn") + "\n")
		}
	} else {
		fmt.Println(utils.T("logging.disabled"))
	}
	log.Println(utils.T("server.logger.success"))

	// 初始化存储
	log.Println(utils.T("server.storage.init"))
	taskStore, err := storage.NewTaskStore()
	if err != nil {
		log.Fatalf(utils.T("server.storage.failed"), err)
	}
	log.Println(utils.T("server.storage.success"))

	log.Println(utils.T("server.logstore.init"))
	logStore, err := storage.NewLogStore()
	if err != nil {
		log.Fatalf(utils.T("server.logstore.failed"), err)
	}
	log.Println(utils.T("server.logstore.success"))

	// 初始化任务执行服务
	log.Println(utils.T("server.execution.init"))
	executionService := service.NewTaskExecutionService()
	log.Println(utils.T("server.execution.success"))

	// 初始化调度器
	log.Println(utils.T("server.scheduler.init"))
	schedulerInstance := scheduler.New(taskStore, logStore, executionService)
	defer schedulerInstance.Stop()
	log.Println(utils.T("server.scheduler.success"))

	// 启动调度器（加载已有任务）
	log.Println(utils.T("server.scheduler.start"))
	if err := schedulerInstance.Start(); err != nil {
		log.Fatalf(utils.T("server.scheduler.failed"), err)
	}
	log.Println(utils.T("server.scheduler.started"))

	// 一次性迁移：为启用但没有NextRun的任务计算下次执行时间
	log.Println(utils.T("server.nextrun.check"))
	migrateTaskNextRun()
	log.Println(utils.T("server.nextrun.completed"))

	// 创建认证配置
	log.Println(utils.T("server.auth.init"))
	authConfig := &handlers.AuthConfig{
		Username:  cfg.Auth.Username,
		Password:  cfg.Auth.Password, // 使用已加密的密码
		JWTSecret: *jwtSecret,
		TokenTTL:  24 * time.Hour,
	}
	log.Println(utils.T("server.auth.success"))

	// 设置路由
	log.Println(utils.T("server.routes.init"))
	router := routes.SetupRoutes(cfg, embeddedDist, schedulerInstance, authConfig, taskStore, logStore, executionService)
	log.Println(utils.T("server.routes.success"))

	// 打印启动信息
	log.Println(utils.T("server.info.print"))
	printStartupInfo(cfg, cfg.Auth.Username, "******")

	// 启动服务器
	addr := cfg.Server.IP + ":" + cfg.Server.Port
	fmt.Printf(utils.T("server.listening") + "\n", cfg.Server.IP, cfg.Server.Port)
	log.Printf(utils.T("server.started") + ": %s", addr)
	if err := http.ListenAndServe(addr, router); err != nil {
		log.Fatalf(utils.T("server.database.failed"), err)
	}
}

func printStartupInfo(cfg *config.Config, username, password string) {
	localIP := utils.GetLocalIP()
	
	fmt.Println(utils.T("server.started"))
	fmt.Printf(utils.T("server.listening") + "\n", cfg.Server.IP, cfg.Server.Port)
	fmt.Printf(utils.T("server.webui.access") + "\n", localIP, cfg.Server.Port)
	
	// 显示认证信息
	fmt.Println(utils.T("server.credentials"))
	fmt.Printf(utils.T("server.username") + "\n", username)
	fmt.Printf(utils.T("server.password") + "\n", password)
	
	// 显示注意事项
	fmt.Println(utils.T("server.notes"))
	fmt.Printf(utils.T("server.note.browser") + "\n")
	fmt.Printf(utils.T("server.note.network") + "\n", cfg.Server.Port)
	fmt.Printf(utils.T("server.note.data") + "\n", cfg.Database.Path)
}

// migrateTaskNextRun 为启用的任务计算NextRun字段（一次性迁移）
func migrateTaskNextRun() {
	var tasks []database.Task
	if err := database.DB.Where("enabled = ? AND (next_run IS NULL OR next_run = ?)", true, time.Time{}).Find(&tasks).Error; err != nil {
		log.Printf(utils.T("migration.query.failed"), err)
		return
	}

	if len(tasks) == 0 {
		log.Println(utils.T("migration.no.tasks"))
		return
	}

	log.Printf(utils.T("migration.found.tasks"), len(tasks))
	
	parser := cron.NewParser(cron.Second | cron.Minute | cron.Hour | cron.Dom | cron.Month | cron.Dow)
	
	for _, task := range tasks {
		if sched, err := parser.Parse(task.Schedule); err == nil {
			nextRun := sched.Next(time.Now())
			if !nextRun.IsZero() {
				if err := database.DB.Model(&task).Update("next_run", nextRun).Error; err != nil {
					log.Printf(utils.T("migration.update.failed"), task.Name, err)
				} else {
					log.Printf(utils.T("migration.update.success"), task.Name, nextRun.Format("2006-01-02 15:04:05"))
				}
			}
		} else {
			log.Printf(utils.T("migration.cron.invalid"), task.Name, err)
		}
	}
}

// printVersionInfo 显示版本信息
func printVersionInfo() {
	fmt.Printf("%s\n", utils.T("version.app.name"))
	fmt.Printf(utils.T("version.version")+"\n", Version)
	fmt.Printf(utils.T("version.build.date")+"\n", BuildDate)
	fmt.Printf(utils.T("version.git.commit")+"\n", GitCommit)
	fmt.Printf(utils.T("version.go.version")+"\n", runtime.Version())
	fmt.Printf(utils.T("version.os.arch")+"\n", runtime.GOOS, runtime.GOARCH)
	fmt.Printf("\n%s\n", utils.T("version.copyright"))
} 